package com.blyat.xsoft.admin.aotuconfigure;

import com.blyat.xsoft.kernel.component.mybatis.dialect.DialectFactory;
import com.blyat.xsoft.kernel.component.mybatis.interceptor.EscapeCharInterceptor;
import com.blyat.xsoft.kernel.component.mybatis.interceptor.PaginationInterceptor;
import com.blyat.xsoft.kernel.restful.entity.BaseEntity;
import org.apache.ibatis.session.LocalCacheScope;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;

/**
 * @Auther: syh
 * @Date: 2020/7/14
 * @Description:
 */
@Configuration
@MapperScan(basePackages = {
        "com.blyat.xsoft.admin.restful.mapper"
}, sqlSessionTemplateRef = "sqlSessionTemplate")
public class MybatisConfiguration {

    @Value("${jdbc.database.type:MYSQL}")
    private String databaseType;

    @Autowired
    DataSource dataSource;

    @Bean(name = "sqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    @Bean(name = "sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setTypeAliasesPackage("com.blyat.xsoft.admin.restful.entity");
        bean.setTypeAliasesSuperType(BaseEntity.class);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources(String.format("classpath*:mapper/%s/**/*.xml", databaseType.toLowerCase())));

        SqlSessionFactory factory = bean.getObject();
        // 使全局的映射器启用或禁用缓存
        factory.getConfiguration().setCacheEnabled(true);
        // 全局启用或禁用延迟加载。当禁用时，所有关联对象都会即时加载
        factory.getConfiguration().setLazyLoadingEnabled(true);
        // 当返回行的所有列都是空时，MyBatis默认返回null。 当开启这个设置时，MyBatis会返回一个空实例。
        factory.getConfiguration().setReturnInstanceForEmptyRow(true);
        // 设置本地缓存范围 session:就会有数据的共享  statement:语句范围 (这样就不会有数据的共享 ) default:session
        factory.getConfiguration().setLocalCacheScope(LocalCacheScope.STATEMENT);
        // 使用驼峰命名法转换字段
        factory.getConfiguration().setMapUnderscoreToCamelCase(true);
        // 分页拦截器
        factory.getConfiguration().addInterceptor(paginationInterceptor());
        // 统一处理mysql查询条件中含有通配符%和_的问题
        factory.getConfiguration().addInterceptor(escapeCharInterceptor());
        // 在null时也调用 setter,适应于返回Map,3.2版本以上可用
        factory.getConfiguration().setCallSettersOnNulls(true);
        // 设置但JDBC类型为空时,某些驱动程序 要指定值,default:OTHER，插入空值时不需要指定类型
        factory.getConfiguration().setJdbcTypeForNull(JdbcType.NULL);
        return factory;
    }

    private PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor interceptor = new PaginationInterceptor();
        interceptor.setDialect(DialectFactory.build(databaseType));
        return interceptor;
    }

    private EscapeCharInterceptor escapeCharInterceptor() {
        EscapeCharInterceptor interceptor = new EscapeCharInterceptor();
        interceptor.setDialect(DialectFactory.build(databaseType));
        return interceptor;
    }
}
